package com.ruoyi.comparison.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.comparison.domain.TaskCheck;
import com.ruoyi.comparison.domain.TaskFile;
import com.ruoyi.comparison.domain.TaskResult;
import com.ruoyi.comparison.domain.TaskResultDetail;
import com.ruoyi.comparison.domain.bo.TaskCheckBo;
import com.ruoyi.comparison.domain.vo.TaskCheckVo;
import com.ruoyi.comparison.mapper.TaskCheckMapper;
import com.ruoyi.comparison.mapper.TaskFileMapper;
import com.ruoyi.comparison.service.ITaskCheckService;
import com.ruoyi.comparison.service.ITaskFileService;
import com.ruoyi.comparison.service.ITaskResultDetailService;
import com.ruoyi.comparison.service.ITaskResultService;
import com.ruoyi.comparison.utils.*;
import lombok.RequiredArgsConstructor;
import org.json.JSONObject;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static java.util.concurrent.Executors.newFixedThreadPool;

/**
 * 查重任务Service业务层处理
 *
 * @author ruoyi
 * @date 2023-11-05
 */
@RequiredArgsConstructor
@Service
public class TaskCheckServiceImpl implements ITaskCheckService {

    private final TaskCheckMapper baseMapper;
    private final ITaskResultService resultService;
    private final ITaskResultDetailService detailService;
    private final WebSocketServer webSocketServer;
    private final KeyHandleUtil keyHandleUtil;
    private final TaskFileMapper fileMapper;

    /**
     * 查询查重任务
     */
    @Override
    public TaskCheckVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询查重任务列表
     */
    @Override
    public TableDataInfo<TaskCheckVo> queryPageList(TaskCheckBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TaskCheck> lqw = buildQueryWrapper(bo);
        String username = LoginHelper.getUsername();
        lqw.eq(TaskCheck::getCreateBy,username);
        Page<TaskCheckVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询查重任务列表
     */
    @Override
    public List<TaskCheckVo> queryList(TaskCheckBo bo) {
        LambdaQueryWrapper<TaskCheck> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TaskCheck> buildQueryWrapper(TaskCheckBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TaskCheck> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getStatus() != null, TaskCheck::getStatus, bo.getStatus());
        lqw.like(StringUtils.isNotBlank(bo.getProjectName()), TaskCheck::getProjectName, bo.getProjectName());
        lqw.like(StringUtils.isNotBlank(bo.getBidName()), TaskCheck::getBidName, bo.getBidName());
        lqw.eq(StringUtils.isNotBlank(bo.getBidUrl()), TaskCheck::getBidUrl, bo.getBidUrl());
        lqw.like(StringUtils.isNotBlank(bo.getInviteBidName()), TaskCheck::getInviteBidName, bo.getInviteBidName());
        lqw.eq(StringUtils.isNotBlank(bo.getInviteBidUrl()), TaskCheck::getInviteBidUrl, bo.getInviteBidUrl());
        return lqw;
    }

    /**
     * 新增查重任务
     */
    @Override
    public Boolean insertByBo(TaskCheck taskCheck) {
        String username = LoginHelper.getUsername();
        taskCheck.setStatus("准备中");
        taskCheck.setCreateBy(username);
        taskCheck.setCreateTime(new Date());
        return baseMapper.insert(taskCheck) > 0;
    }

    /**
     * 修改查重任务
     */
    @Override
    public Boolean updateByBo(TaskCheckBo bo) {
        TaskCheck update = BeanUtil.toBean(bo, TaskCheck.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TaskCheck entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除查重任务
     */
    @Override
    public Boolean deleteWithValidByIds(List<Long> ids) {
        boolean b = this.baseMapper.deleteBatchIds(ids) > 0;
        List<TaskCheckVo> taskCheckVos = this.baseMapper.selectVoBatchIds(ids);
        List<Long> collect1 = taskCheckVos.stream().peek(taskCheckVo -> taskCheckVo.getStatus().equals("已完成")).map(TaskCheckVo::getId).collect(Collectors.toList());
        if (!ObjectUtil.isEmpty(collect1)){
            boolean s = resultService.deleteByResultId(ids);

            LambdaQueryWrapper<TaskFile> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(TaskFile::getCheckId,ids);
            fileMapper.delete(wrapper);
            List<TaskResult> list=resultService.selsectByIds(ids);
            List<Long> collect2 = list.stream().map(TaskResult::getId).collect(Collectors.toList());
            detailService.deleteWithValidByIds(collect2);
        }
        return b;
    }

    @Override
    public void updateById(TaskCheck taskCheck) {
        baseMapper.updateById(taskCheck);
    }

    private static String fileDir1 = "D:\\dev\\RuoYi-Vue-Plus\\ruoyi-admin\\fileStorage\\pdf\\";//目标文件夹
    private static String DESTFILE_SUFFIX = ".pdf";//文件后缀
    private static final String fileDir = "/fileStorage/pdf/";
    private static final String path = "/ruoyi/server/temp";

    @Override
    public void startTask(Long id) throws Exception {
        TaskCheckVo taskCheckVo = this.baseMapper.selectVoById(id);
        if (!(taskCheckVo.getStatus().equals("准备中")))
            return;
        String bidUrl = taskCheckVo.getBidUrl();
        String inviteBidUrl = taskCheckVo.getInviteBidUrl();
        String[] bids = bidUrl.split(",");
        String[] inviteBids = inviteBidUrl.split(",");
        int a=1;
        for (int i = 0; i < inviteBids.length-1; i++) {
            for (int j = a; j < inviteBids.length; j++) {
                TenderCompare tenderCompare = new TenderCompare(inviteBids[i],inviteBids[j],15, bids[0],taskCheckVo.getProjectName());
                List<String> duplicates = tenderCompare.getDuplicatedWords();
                if (ObjectUtil.isEmpty(duplicates))
                    return;
                List<TaskResultDetail> list=new ArrayList<>();
                /*需要转换的文件*/
                // word文件
                File file1 = new File(inviteBids[i]);
                File file2 = new File(inviteBids[j]);
                String name1 = file1.getName();
                String name2 = file2.getName();

                String destFileName1 = name1.substring(0, name1.lastIndexOf("."));//获取不带后缀的文件名
                String s1 =fileDir1 + destFileName1 + DESTFILE_SUFFIX;
                // 转换之后文件生成的地址
                File newFile = new File(fileDir1);
                if (!newFile.exists()) {
                    newFile.mkdirs();
                }
                AsposeUtil.wordToPdf(inviteBids[i],s1);
                String destFileName2 = name2.substring(0, name2.lastIndexOf("."));//获取不带后缀的文件名
                String s2 =fileDir1 + destFileName2 + DESTFILE_SUFFIX;
                AsposeUtil.wordToPdf(inviteBids[j],s2);

                Set<String> set = new HashSet<>(duplicates);
                Set<String> set1 = keyHandleUtil.PDFByKeyWord(s1, set);
                Set<String> set2 = keyHandleUtil.PDFByKeyWord(s2, set1);
                Map<String, Integer> map1 = PDFUtil.PDFByKeyWord(s1,set2);
                Map<String, Integer> map2 = PDFUtil.PDFByKeyWord(s2,set2);

                HashMap<String, String> smap = tenderCompare.newRedProgramListDoc();
                String s3 = "";
                String s4 = "";
                for (String key : smap.keySet()) {
                    /*需要转换的文件*/
                    String name3 = new File(key).getName();
                    String name4 = new File(smap.get(key)).getName();

                    String fileName1 =name3+UUID.randomUUID().toString().replaceAll("-","").substring(0,6)+DESTFILE_SUFFIX;
                    String fileName2 =name4+UUID.randomUUID().toString().replaceAll("-","").substring(0,6)+DESTFILE_SUFFIX;
                    s3 =fileDir1 + fileName1;
                    AsposeUtil.wordToPdf(key,s3);
                    s4 =fileDir1 + fileName2;
                    AsposeUtil.wordToPdf(smap.get(key),s4);
                }

                for (String s : set2) {
                    TaskResultDetail bo = new TaskResultDetail();
                    bo.setLeftNum(Long.valueOf(map1.get(s)));
                    bo.setRightNum(map2.get(s));
                    bo.setLeftName(name1);
                    bo.setRightName(name2);
                    bo.setPreNum(s.length());
                    bo.setLightWord(s);
                    bo.setLeftBidUrl(s1);
                    bo.setLeftFormUrl(s3);
                    bo.setRightBidUrl(s2);
                    bo.setRightFormUrl(s4);
                    for (String d : duplicates) {
                        if (s.equals(d)){
                            bo.setPreWord(d);
                            break;
                        }else if (d.contains(s)){
                            bo.setPreWord(d);
                            bo.setRemark("提示：高亮内容与重复内容不一致，请联系上下文比对确认");
                            break;
                        }
                    }
                    list.add(bo);
                }

                TaskResult taskResult = new TaskResult();
                taskResult.setCheckId(id);
                taskResult.setLeftName(name1);
                taskResult.setRightName(name2);
                taskResult.setCreateTime(new Date());
                taskResult.setPrefix(String.valueOf(tenderCompare.calculateSimilarity()));
                resultService.insert(taskResult);
                List<TaskResultDetail> collect = list.stream().peek(resultDetail -> resultDetail.setResultId(taskResult.getId())).collect(Collectors.toList());
                detailService.insertByBoList(collect);
                System.out.println(collect);
            }
            a++;
        }
        TaskCheck taskCheck = new TaskCheck();
        taskCheck.setId(id);
        taskCheck.setStatus("已完成");
        this.baseMapper.updateById(taskCheck);
        try {
            //发送内容
            JSONObject jsonObject=new JSONObject();
            String message="已完成";
            jsonObject.put("message",message);
            webSocketServer.sendAllMessage(jsonObject.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean checkProjectNamUnique(TaskCheck taskCheck) {
        boolean exist = this.baseMapper.exists(new LambdaQueryWrapper<TaskCheck>()
            .eq(TaskCheck::getProjectName, taskCheck.getProjectName()));
        return !exist;
    }
}
